package server;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import javax.imageio.ImageIO;

/**
 * Receive images from a single user. <br>
 * "n" istances for "n" users
 * 
 * @author Michele Massaro 1057513
 *
 */
public class ConnectionThread implements Runnable {

	private int id;
	private UserList userList;
	private Socket client;
	private String clientIP;
	private String imagePATH;
	private String thumbPATH;

	public ConnectionThread(Socket client, UserList list, String imagePATH, String thumbPATH) {
		this.userList = list;
		this.id = list.getNewID();
		this.client = client;
		this.clientIP = this.client.getInetAddress().getHostAddress();
		this.imagePATH = imagePATH;
		this.thumbPATH = thumbPATH;
		System.out.println("SERVER: client " + this.id + " connected from "
				+ this.clientIP);
	}

	@Override
	public void run() {
		InputStream in = null;
		OutputStream out = null;

		try {
			String reading = null;
			BufferedImage image = null;
			
			// set socket timeout
			client.setSoTimeout(30000);
			
			in = client.getInputStream();
			out = client.getOutputStream();
			reading = receiveString(in);
				
			// DEBUG
			//System.out.println("SERVER: received string " + reading + " from " + id);
			
			// String format:
			// "image <width>x<height> <byte array length> \n"
			
			while(reading.indexOf("image") >= 0) { // check if word "image" is inside the received string
				String[] split = reading.split(" ");
				int parts = Integer.parseInt(split[2].trim());
				byte[] array = new byte[parts];
				
				int counter = 0;
				int left = parts;
				while(left > 0) {
					int readCount = in.read(array, counter, left);
					if (readCount < 0)
						break;
					counter = counter + readCount;
					left = left - readCount;
				}
				
				// send ack to client
				String ack = "ack\n";
				byte[] strB = ack.getBytes();
				out.write(strB);
				out.flush();
				
				// save image
				File save = new File(imagePATH + id + ".jpg");
				FileOutputStream imageFile = new FileOutputStream(save);
				try {
					imageFile.write(array);
				} finally {
					imageFile.close();
				}
				
				// DEBUG
				//System.out.println("SERVER: image saved for id " + id);
				
				ByteArrayInputStream byteStream = new ByteArrayInputStream(array);
				image = ImageIO.read(byteStream);
				
				if(image != null) {					
					
					// get original resolution
					String[] resolution = split[1].split("x");
					double originalWidth = Integer.parseInt(resolution[0]);
					double originalHeight = Integer.parseInt(resolution[1]);
					// DEBUG
					//System.out.println("image resolution: " + originalWidth + "x" + originalHeight);
					
					// create thumbnail
					int height = 150;
					double ratio = originalWidth/originalHeight;
					// DEBUG
					//System.out.println("ratio: " + ratio);
					int width = (int) (height * ratio);
					// DEBUG
					//System.out.println("image thumbnail: " + width + "x" + height);
					BufferedImage thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
					Graphics2D gr = thumbnail.createGraphics();
					gr.drawImage(image, 0, 0, width, height, null);
					gr.dispose();
					
					// save thumbnail
					save = new File(thumbPATH + id + ".jpg");
					ImageIO.write(thumbnail, "jpg", save);
					
					System.out.println("image received from user " + id);
					
					// DEBUG
					//System.out.println("SERVER: thumbnail saved for id " + id);
					
				}
				
				reading = receiveString(in);
				if(reading == null)
					break;
			}
			
		} catch (IOException e) {
			System.out.println(" error with connection n." + id + " with host "
					+ clientIP);
		} catch (NullPointerException e) {
			e.printStackTrace();
		} finally {
			try {
				
				// delete thumbnail
				File thumbnail = new File(thumbPATH + id + ".jpg");
				thumbnail.delete();
				
				// delete image
				File image = new File(imagePATH + id + ".jpg");
				image.delete();
				
				client.close();
				userList.removeUser(id);
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("connection n." + id + " with host " + clientIP
					+ " ended");
		}

	}
	
	private String receiveString(InputStream in) throws IOException {
		
		byte[] reading = new byte[100];
		int count = 0;
		while(true) {
			if(count == 100)
				throw new IOException();
			int read = in.read();
			if((read == (int)'\n') || (read < 0))
				break;
			reading[count++] = (byte) read;
		}
		if(count == 0)
			return null;
		return new String(reading, 0, count);
	}

}
